package com.ciaojian.worker.controller;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ciaojian.core.enums.business.WorkerApplyStatusEnum;
import com.ciaojian.core.mapper.SchedulingMapper;
import com.ciaojian.core.model.EatTime;
import com.ciaojian.core.model.Scheduling;
import com.ciaojian.core.model.SchedulingExamine;
import com.ciaojian.core.model.Worker;
import com.ciaojian.core.model.dto.SchedulingDTO;
import com.ciaojian.core.model.group.Save;
import com.ciaojian.core.util.RedisUtil;
import com.ciaojian.core.util.Result;
import com.ciaojian.core.util.StringUtil;
import com.ciaojian.worker.model.query.SchedulingApplyQuery;
import com.ciaojian.worker.model.vo.SchedulDelVo;
import com.ciaojian.worker.service.SchedulingExamineServiceImpl;
import com.ciaojian.worker.service.SchedulingServiceImpl;
import io.swagger.annotations.*;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author Atlakyn
 */
@Validated
@Api(tags = "排班")
@RestController
@RequestMapping("/schedules")
public class SchedulingController {
    @Resource
    private SchedulingExamineServiceImpl schedulingExamineService;
    @Resource
    private SchedulingServiceImpl schedulingService;

    @ApiOperation(value = "日程详情(按日期范围)", response = SchedulingDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "门店Id", name = "storeId"),
            @ApiImplicitParam(value = "开始日期", name = "beginDate", paramType = "query"),
            @ApiImplicitParam(value = "结束日期", name = "endDate", paramType = "query")
    })
    @GetMapping("/detail-date")
    public Result getDetailBetweenDate(@NotNull(message = "门店Id不能为空") Integer storeId,
                                       @NotNull(message = "开始时间不能为空") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate,
                                       @NotNull(message = "结束时间不能为空") @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
        return Result.ok(schedulingService.getBaseMapper().findByStoreBetween(storeId, beginDate, endDate));
    }

    @ApiOperation(value = "日程详情(按单日)", response = SchedulingDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "发型师ID", name = "workerId"),
            @ApiImplicitParam(value = "日期", name = "day", paramType = "query")
    })
    @GetMapping("/detail-day")
    public Result getDetailByDay(@NotNull(message = "发型师ID不能为空") Integer workerId,
                                 @NotNull(message = "日期不能为空") @DateTimeFormat(pattern = "yyyy-MM-dd") Date day) {
        return Result.ok(schedulingService.getBaseMapper().findByWorkerAndDate(workerId, day));
    }

    @ApiOperation(value = "发型师排班日历", response = SchedulingDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "发型师ID", name = "workerId"),
            @ApiImplicitParam(value = "月份", name = "month", paramType = "query")
    })
    @GetMapping("/calendar")
    public Result calendar(@NotNull(message = "发型师ID不能为空") Integer workerId,
                           @NotNull(message = "日期不能为空") @DateTimeFormat(pattern = "yyyy-MM") Date month) {
        return Result.ok(schedulingService.getBaseMapper().findCalendarByWorker(workerId, month));
    }

    @ApiOperation("撤销申请")
    @PostMapping("/withdraw/{examineId}")
    public Result withdraw(@PathVariable Integer examineId) {
        LambdaUpdateWrapper<SchedulingExamine> examineUpdateWrapper = new LambdaUpdateWrapper<>();
        examineUpdateWrapper.set(SchedulingExamine::getLogicDel, Boolean.TRUE)
                .eq(SchedulingExamine::getId, examineId);
        examineUpdateWrapper.set(SchedulingExamine::getStatus,WorkerApplyStatusEnum.DISMISSED);
        schedulingExamineService.update(examineUpdateWrapper);

        LambdaUpdateWrapper<Scheduling> schedulingUpdateWrapper = new LambdaUpdateWrapper<>();
        schedulingUpdateWrapper.set(Scheduling::getLogicDel, Boolean.TRUE).eq(Scheduling::getExamineId, examineId);
        schedulingUpdateWrapper.set(Scheduling::getStatus,WorkerApplyStatusEnum.DISMISSED);
        schedulingService.update(schedulingUpdateWrapper);

        return Result.ok();
    }

    @ApiOperation("变为已读")
    @PostMapping("/examines/read")
    public Result read(Integer workerId, WorkerApplyStatusEnum status) {
        LambdaUpdateWrapper<SchedulingExamine> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(SchedulingExamine::getRead, true)
                .eq(SchedulingExamine::getWid, workerId)
                .eq(SchedulingExamine::getStatus, status);
        return Result.save(new SchedulingExamine().update(lambdaUpdateWrapper));
    }

    @ApiOperation(value = "审核详情", response = Scheduling.class)
    @GetMapping("/examines/detail/{examineId}")
    public Result getDetail(@ApiParam(value = "审核记录id") @PathVariable Integer examineId) {
        return Result.ok(schedulingService.getBaseMapper().findByExamineId(examineId));
    }

    @ApiOperation("排班通知列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "状态", value = "status", dataTypeClass = WorkerApplyStatusEnum.class)
    })
    @ApiResponses({
            @ApiResponse(response = SchedulingExamine.class, code = 200, message = "success")
    })
    @GetMapping("/examines")
    public Result getScheduleExamine(@NotNull(message = "请选择门店") Integer storeId,
                                     @NotNull(message = "请选择排班状态") WorkerApplyStatusEnum status,
                                     @RequestParam(defaultValue = "0") Integer pageNo,
                                     @RequestParam(defaultValue = "6") Integer pageSize) {
        LambdaQueryWrapper<SchedulingExamine> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SchedulingExamine::getStoreId, storeId)
                .eq(SchedulingExamine::getStatus, status)
                .eq(SchedulingExamine::getLogicDel, Boolean.FALSE)
                .orderByDesc(SchedulingExamine::getCreateTime);
        return Result.ok(new SchedulingExamine().selectPage(new Page<>(pageNo, pageSize), lambdaQueryWrapper));
    }

    @ApiOperation("审核通知数")
    @GetMapping("/apply-notice")
    public Result applyNotice(Integer storeId) {
        LambdaQueryWrapper<SchedulingExamine> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SchedulingExamine::getStoreId, storeId)
                .eq(SchedulingExamine::getRead, Boolean.FALSE)
                .eq(SchedulingExamine::getLogicDel, Boolean.FALSE);
        return Result.ok(new SchedulingExamine().selectCount(lambdaQueryWrapper));
    }

    @ApiOperation("本月已排班的日期")
    @GetMapping("/scheduled-month")
    public Result getScheduledMonth(
            @NotNull(message = "请选择门店") Integer storeId,
            @NotNull(message = "请选择开始日期") @DateTimeFormat(pattern = "yyyy-MM-dd") Date begin,
            @NotNull(message = "请选择结束日期") @DateTimeFormat(pattern = "yyyy-MM-dd") Date end
    ) {
        LambdaQueryWrapper<Scheduling> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(Scheduling::getDate)
                .between(Scheduling::getDate, begin, end)
                .eq(Scheduling::getStoreId, storeId)
                .eq(Scheduling::getStatus, WorkerApplyStatusEnum.PASS)
                .eq(Scheduling::getLogicDel, Boolean.FALSE)
                .groupBy(Scheduling::getDate);
        return Result.ok(schedulingService.listObjs(lambdaQueryWrapper));
    }

    @ApiOperation("查询已排班的发型师")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "date", value = "日期", paramType = "query"),
            @ApiImplicitParam(name = "rosterId", value = "排班Id"),
            @ApiImplicitParam(name = "storeId", value = "门店Id")
    })
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功返回数据", response = Scheduling.class)})
    @GetMapping
    public Result getScheduled(@DateTimeFormat(pattern = "yyyy-MM-dd") @NotNull(message = "日期不能为空") Date date,
                               Integer rosterId,
                               Integer storeId
    ) {
        LambdaQueryWrapper<Scheduling> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Scheduling::getDate, date)
                .eq(Scheduling::getRosterId, rosterId)
                .eq(Scheduling::getStatus, WorkerApplyStatusEnum.PASS)
                .eq(Scheduling::getLogicDel, Boolean.FALSE)
                .eq(Scheduling::getStoreId, storeId);
        return Result.ok(new Scheduling().selectList(lambdaQueryWrapper));
    }

    @ApiOperation("提交排班申请")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/apply")
    public Result apply(@RequestBody @Validated(Save.class) SchedulingApplyQuery schedulingApplyBO) {
        return Result.save(schedulingService.apply(schedulingApplyBO));
    }

    @ApiOperation("查询排班申请记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店id", paramType = "query"),
            @ApiImplicitParam(name = "pageNo", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", paramType = "query"),
            @ApiImplicitParam(name = "startDate", value = "开始时间", paramType = "query"),
            @ApiImplicitParam(name = "endDate", value = "结束时间", paramType = "query")
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "SUCCESS", response = SchedulingExamine.class)
    })
    @GetMapping("/examine/record")
    public Result getRecord(Integer workerId,
                            @RequestParam(defaultValue = "0") Integer pageNo,
                            @RequestParam(defaultValue = "6") Integer pageSize,
                            WorkerApplyStatusEnum status
    ) {
        return Result.ok(schedulingExamineService.getBaseMapper().findByStoreId(workerId, status, new Page<>(pageNo, pageSize)));
    }

    @GetMapping("/worker")
    public Result getScheduled(Integer workerId,
                               @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
                               @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
        LambdaQueryWrapper<Scheduling> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Scheduling::getWorkerId, workerId)
                .ge(Scheduling::getDate, startDate)
                .le(Scheduling::getDate, endDate);
        return Result.ok(new Scheduling().selectList(lambdaQueryWrapper));
    }

    @ApiOperation("发型师删除指定日期排班")
    @PostMapping("/delschedul")
    public Result delschedul(@RequestBody SchedulDelVo schedulDelVo) {

            return schedulingService.delWorkerDate(schedulDelVo.getWorkerId(), schedulDelVo.getDelDate());

    }

    /**
     * 查看发型师是否时间段就餐
     * @param workerId
     * @return
     */
    @ApiOperation("查看发型师是否时间段就餐")
    @GetMapping("/workerEatType")
    public Result getScheduled(Integer workerId) {
        Worker worker = new Worker().selectById(workerId);
        if (ObjectUtil.isNull(worker)){
            return Result.error("无员工");
        }

        if (ObjectUtil.isNotNull(worker.getEatTimeId())&&worker.getEatTimeId()!=0){
            EatTime eatTime = new EatTime().selectById(worker.getEatTimeId());
            if (ObjectUtil.isNull(eatTime)){
                return Result.error("该员工没有安排就餐时间");
            }

            return Result.ok(eatTime);

        }
        return Result.error("系统错误");
    }

    /**
     * 发型师选择就餐时间
     * @param workerId
     * @return
     */
    @ApiOperation("发型师选择就餐时间")
    @GetMapping("/changeEatdate")
    public Result changeEatdate(Integer workerId,
                                @ApiParam(value = "1午餐 2晚餐") Integer type,
                                @DateTimeFormat(pattern = "yyyy-MM-dd") Date day,
                                @RequestParam(required = false) @DateTimeFormat(pattern = "HH:mm:ss") Date lunchDate,
                                @RequestParam(required = false) @DateTimeFormat(pattern = "HH:mm:ss") Date dinnerDate) {

        LambdaQueryWrapper<Scheduling> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Scheduling::getWorkerId, workerId)
                .eq(Scheduling::getDate, day)
                .eq(Scheduling::getStatus,1)
                .eq(Scheduling::getType,0);
        Scheduling scheduling = new Scheduling().selectOne(lambdaQueryWrapper);

        if(ObjectUtil.isNull(scheduling)){

            return Result.error("暂无排班");
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String dayStr = dateFormat.format(day);
        String keyTime = RedisUtil.getKey("EatTime::"+type+"::" + workerId + "::"+dayStr);
        if (ObjectUtil.isNotNull(keyTime)){
            if (dayStr.equals(keyTime)){
                return Result.error("无法更改,今日已设置");
            }
        }

        Worker worker = new Worker().selectById(workerId);
        if (ObjectUtil.isNotNull(worker.getEatTimeId())&&worker.getEatTimeId()!=0){
            try {
                EatTime eatTime = new EatTime().selectById(worker.getEatTimeId());

                if (type==1) {
                    if (lunchDate.getTime() < eatTime.getLunchStartTime().getTime() || lunchDate.getTime() > eatTime.getLunchEndTime().getTime()) {
                        return Result.error("请选择规定时间就餐");
                    }
                }

                if (type==2) {
                    if (dinnerDate.getTime() < eatTime.getDinnerStartTime().getTime() || dinnerDate.getTime() > eatTime.getDinnerEndTime().getTime()) {
                        return Result.error("请选择规定时间就餐");
                    }
                }
            }catch (Exception e){
                return Result.error("请选择规定时间就餐");
            }
        }else {
            return Result.error("无法设置");
        }


        //就餐时间
        //午餐
        if(type==1) {
            Time lunchTime = new Time(lunchDate.getTime());
            Time lunchEndTime = new Time(lunchDate.getTime() + 1800000);

            scheduling.setLunchStartTime(lunchTime);
            scheduling.setLunchEndTime(lunchEndTime);

        }
        //晚餐
        if(type==2) {
            Time dinnerTime = new Time(dinnerDate.getTime());
            Time dinnerEndTime = new Time(dinnerDate.getTime() + 1800000);
            scheduling.setDinnerStartTime(dinnerTime);
            scheduling.setDinnerEndTime(dinnerEndTime);
        }

        boolean b = scheduling.updateById();
        if (b){
            RedisUtil.setKeyTime("EatTime::"+type+"::" + workerId + "::"+dayStr,RedisUtil.getRemainSecondsOneDay(new Date()),dayStr, DateUnit.SECOND);
            return Result.ok("设置成功");
        }
        return Result.error("系统错误");
    }


}